using System;
using System.Linq;
using System.Collections.Generic;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.IO;


namespace collabr8
{
    public partial class ServerForm : Form
    {
        private delegate void UpdateStatusCallback(string strMessage);
        // private delegate void UpdateFrameCallback();
        private delegate void UpdateClipCallback(string strName);
        private delegate void EndSharingCallback();
        public delegate void ShareArea();
        public delegate void DoSendClip(string fn);
        private Server server;
        private Keys key1, key2;
        // if the 'size' parameter is set, it becomes true. If the shortcut is pressed, it returns false
        private bool usingWindow = false;
        private bool selectedMethod = false;
        // private MonitorForm monitorForm = null; // used to preview screen's area
        private ClipboardForm clipboardForm = null;
        private SizerForm sizerForm;
        private int x=0, y=0, width=300, height=200;
        private ArrayList windows;
        public ShareArea delegateShareArea;
        public DoSendClip delegateSendClip;
  

        public ServerForm()
        {
            server = Server.Instance;
            InitializeComponent();
            this.delegateShareArea = new ShareArea(this.ChangeScreenArea);
            this.delegateSendClip = new DoSendClip(server.SendClip);
            this.windows = new ArrayList();
            this.comboBoxKey1.SelectedIndex = 0;
            this.comboBoxKey2.SelectedIndex = 0;
            this.comboBoxWin.SelectedIndex = 0;
            this.key1 = Keys.Control;
            this.key2 = Keys.Q;
            this.clipboardForm = new ClipboardForm(this);
            //server.FrameEncoded += new FrameEncodedEventHandler(mainServer_FrameEncoded);
            server.ClipReceived += new ClipReceivedEventHandler(mainServer_ClipReceived);
            server.SharingEnded += new EndScreenSharingHandler(mainServer_SharingEnded);
        }

        private void btnListen_Click(object sender, EventArgs e)
        {
            this.btnListen.Enabled = false;
            this.comboBoxKey1.Enabled = true;
            this.comboBoxKey2.Enabled = true;
            this.comboBoxWin.Enabled = true;
            this.btnSize.Enabled = true;
            // Parse the server's IP address out of the TextBox
            IPAddress ipAddr = IPAddress.Parse(txtIp.Text);
            // Save the port
            Int32 port = Convert.ToInt32(txtPort.Text);
            // Save the password
            String passwordServer = txtSetPassword.Text;
            // Create a new instance of the ChatServer object
            server.InitServer(ipAddr, passwordServer, port);
            // Hook the StatusChanged event handler to mainServer_StatusChanged
            server.StatusChanged += new StatusChangedEventHandler(mainServer_StatusChanged);
            // Start listening for connections
            server.StartListening();
            // Show that we started to listen for connections
            txtLog.AppendText("Monitoring for connections...\r\n");
            this.btnSend.Enabled = true;
            this.txtMessage.Enabled = true;
            this.btnClipboard.Cursor = Cursors.Hand;
        } 

        public void mainServer_StatusChanged(object sender, StatusChangedEventArgs e)
        {
            // Call the method that updates the form
            this.Invoke(new UpdateStatusCallback(this.UpdateStatus), new object[] { e.EventMessage });
        }

        public void mainServer_SharingEnded()
        {
            this.Invoke(new EndSharingCallback(this.EndSharing));
        }

       /* public void mainServer_FrameEncoded()
        {
            // Call the method that updates the form

            this.Invoke(new UpdateFrameCallback(this.UpdateFrame));
        }
        */
        public void mainServer_ClipReceived(object sender, ClipReceivedEventArgs e)
        {
            // Call the method that updates the form
            this.Invoke(new UpdateClipCallback(this.UpdateClip), new object[] { e.EventMessage });
        }

        private void UpdateFrame()
        {
           /* if (!this.usingWindow && this.monitorForm != null)
                this.monitorForm.Picture = server.CurrentFrame; */
        }

        private void EndSharing()
        {
            this.onAir.Visible = false;
        }

        private void UpdateClip(string name)
        {
            this.clipboardForm.AddItem(name);
        }

        private void UpdateStatus(string strMessage)
        {
            // Updates the log with the message
            txtLog.AppendText(strMessage + "\r\n");
        }

        public void SetArea(int x, int y, int width, int height)
        {
            this.x = x;
            this.y = y;
            this.width = width;
            this.height = height;
        }

        private void btnSize_Click(object sender, EventArgs e)
        {
            if(this.sizerForm == null || this.sizerForm.IsDisposed || this.sizerForm.Disposing)
                this.sizerForm = new SizerForm(this);
            if (!this.sizerForm.IsOpen)
                this.sizerForm.Open();
        }



        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (comboBoxKey1.SelectedIndex == 0)
                this.key1 = Keys.Control;
            else
                this.key1 = Keys.Alt;
        }


        protected override bool ProcessCmdKey(ref System.Windows.Forms.Message msg, Keys keyData)
        {
            
            if (keyData == (this.key1 | this.key2))
            {
                if (!this.selectedMethod)
                {
                    MessageBox.Show("Please select screen area or window first");
                    return true;
                }

                if (server.IsSharingScreen)
                {
                    server.StopVideo();
                    this.onAir.Visible = false;
                    /*if(this.monitorForm != null)
                        this.monitorForm.Hide();*/
                }
                else
                {
                    
                    if (!this.btnListen.Enabled)
                    {
                        this.onAir.Visible = true;
                        if (this.usingWindow)
                        {
                            server.startVideo((IntPtr)windows[comboBoxWin.SelectedIndex]);
                            /*if (this.monitorForm != null)
                                this.monitorForm.Hide();*/
                            
                        }
                        else
                        {
                            server.startVideo(this.x, this.y, this.width, this.height);
                            /*if (server.IsSharingScreen)
                            {
                                if (this.monitorForm == null)
                                    this.monitorForm = new MonitorForm(this, this.width, this.height);
                                this.monitorForm.Show();
                            }*/
                        }
                    }
                }

                return true;
            }
            return base.ProcessCmdKey(ref msg, keyData);
        }

        public void ChangeScreenArea()
        {
            // Only for screen area use only! (SizerForm callback)
            this.usingWindow = false;
            server.ChangeVideo(this.x, this.y, this.width, this.height);
        }


        private void comboBoxKey2_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.key2 = (Keys)(((string)comboBoxKey2.SelectedItem)[0]);
        }


        private void btnSend_Click(object sender, EventArgs e)
        {
            if (txtMessage.Lines.Length > 0)
            {
                server.SendAdminMessage(txtMessage.Text);
            }
            txtMessage.Text = "";
        }

        private void btnClipboard_Click(object sender, EventArgs e)
        {
            if (server.IsRunning)
            {
                this.clipboardForm.Show();
            }  
        }

        private void ServerForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            server.StopVideo();
            server.StopListening();
        }

        private void txtMessage_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)13)
            {
                if (txtMessage.Lines.Length > 0)
                {
                    server.SendAdminMessage(txtMessage.Text);
                }
                txtMessage.Text = "";
            }
        }

        private void comboBoxWin_Click(object sender, EventArgs e)
        {
            comboBoxWin.Items.Clear();
            windows.Clear();
            foreach (var process in System.Diagnostics.Process.GetProcesses().Where(p => p.MainWindowHandle != IntPtr.Zero))
            {
                if (process.MainWindowTitle.Trim() != "")
                {
                    comboBoxWin.Items.Add(process.MainWindowTitle);
                    windows.Add(process.MainWindowHandle);
                }
            }
        }

        private void comboBoxWin_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (this.btnSize.Enabled)
            {
                this.usingWindow = true;
                this.selectedMethod = true;
                if (server.IsSharingScreen)
                {
                   /* if (this.monitorForm != null)
                        this.monitorForm.Hide();*/
                    server.ChangeVideo((IntPtr)windows[comboBoxWin.SelectedIndex]);
                }
            }
        }

        public bool IsUsingWindow
        {
            get 
            {
                return this.usingWindow;
            }

            set
            {
                this.usingWindow = value;
            }
        }

        public bool SelectedMethod
        {
            get
            {
                return this.selectedMethod;
            }

            set
            {
                this.selectedMethod = value;
            }
        }

        public bool IsSharingScreen
        {
            get
            {
                return server.IsSharingScreen;
            }
        }

        private void txtSetPassword_TextChanged(object sender, EventArgs e)
        {
            if (txtSetPassword.Text.Trim() != "")
                this.btnListen.Enabled = true;
            else
            {
                this.btnListen.Enabled = false;
                txtSetPassword.Text = "";
            }
        }
       
    }
}